--======================================================================
-- filename: ui_manager.lua
-- descrip: 进行UI管理，在切场景的时候关闭未处理的UI和dialog
-- 这里直接打开的界面必须是多个游戏可以通用的，请勿将本游戏专用的代码放入
--======================================================================
local Tool = Import("logic/common/tool").CTool
local CommonEnum = Import("logic/base/common_enum").Enum
local UIFloatMenu = Import("logic/ui/common/ui_float_menu").CUIFloatMenu
local CUIPnlConfirmDialogLogic = Import("logic/ui/common/pnl_confirm_dialog/ui_pnl_confirm_dialog_logic").CUIPnlConfirmDialogLogic
local CUIPnlAlertDialogLogic = Import("logic/ui/common/pnl_alert_dialog/ui_pnl_alert_dialog_logic").CUIPnlAlertDialogLogic
local ALL_RES_ID = Import("logic/config/info_res_id").resid
local CUIPnlMoneyLogic = Import("logic/ui/money/pnl_money/ui_pnl_money_logic").CUIPnlMoneyLogic
local CUIRewardFloatDialogLogic = Import("logic/ui/task/reward_float_dialog/ui_reward_float_dialog_logic").CUIRewardFloatDialogLogic
local GlobalEnum = Import("logic/base/global_enum").Enum
local UI_EFFECT = GlobalEnum.UI_EFFECT
local UIPnl = Import("logic/config/config_ui_pnl").config
local CUIBtnGaidLogic = Import("logic/ui/btn_gaid/ui_btn_gaid_logic").CUIBtnGaidLogic
local CUIBtnGaidBlackImgLogic = Import("logic/ui/sign/btn_gaid_black_img/ui_btn_gaid_black_img_logic").CUIBtnGaidBlackImgLogic
local UICustomID = GlobalEnum.UICustomID
local CUIPnlConnectingLogic = Import("logic/ui/pnl_connecting/ui_pnl_connecting_logic").CUIPnlConnectingLogic
local CUIPnlReNameLogic = Import("logic/ui/common/pnl_re_name/ui_pnl_re_name_logic").CUIPnlReNameLogic
local CUIChatNewLogic = Import("logic/ui/chat/chat_new/ui_chat_new_logic").CUIChatNewLogic
local CUIPnlSelectResolutionLogic = Import("logic/ui/pnl_select_resolution/ui_pnl_select_resolution_logic").CUIPnlSelectResolutionLogic
local CUIPnlCommonTxtTipsLogic = Import("logic/ui/pnl_common_txt_tips/ui_pnl_common_txt_tips_logic").CUIPnlCommonTxtTipsLogic
local CUIPnlSimpleReconfirmLogic = Import("logic/ui/common/pnl_reconfirm/ui_pnl_simple_reconfirm_logic").CUIPnlSimpleReconfirmLogic
local CUIPnlCaijiItemsEditorLogic = Import("logic/ui/caiji_editor/pnl_caiji_items_editor/ui_pnl_caiji_items_editor_logic").CUIPnlCaijiItemsEditorLogic
local CUIProcessDialogLogic = Import("logic/ui/task/process_dialog/ui_process_dialog_logic").CUIProcessDialogLogic

CUIManager = class()
CUIManager.__name = "CUIManager"

CUIManager.Init = function(self)
	self._uiRootObj = nil
	-- 在ui_root.prefab中直接添加Canvas
	self._uiMsgCanvasObj = nil
	self._uiMainCanvasObj = nil
	self._uiSceneCanvasObj = nil
	self._worldSpaceCanvasObj = nil 
	self._3dUICanvasObj = nil
	self._3dUISceneCanvasObj = nil
	self._uiCamera = nil
	self._3dUICamera = nil
	self._counter = 0
	self._LogicInsList = {}
	self._canvasToPlaneDis = {}
	
	self:InitUiRoot()
	self:InitCommonEvent()

	self._floatDialog = nil
	self._floatMenu = nil
	self._waitingUI = nil
	self._waitingUIRetain = 0
	self._defWaitingUITimeout = 8 --默认等待超时时间（秒）
	self._curWaitingUITimeout = 8 --当前等待超时时间（秒）

	self._asyncLoadingLogicList = {}
end

--外部请勿调用
CUIManager.InitUiRoot = function(self)
	if self._uiRootObj ~= nil then return end
	self._uiRootObj = self:InitAsset("Assets/res/Prefabs/ui/ui_root_ex.prefab")
	-- 因为UI使用了Live2D的资源，Live2D渲染使用了OnRenderObject的方式，导致所有的Camera只要照到Live2D
	-- 资源，都进行渲染，不管是否这个Live2D的Layer，所以，现在避免ui_camera与其他的相机重叠。
	self._uiRootObj.transform.position = Vector3.New(0, -9999, 0)
	--self._uiRootObj = self:InitAssetCommon("Assets/res/Prefabs/ui/ui_root_ex.prefab")
	GameObject.DontDestroyOnLoad(self._uiRootObj)
	--self._uiCamera = GameObject.FindGameObjectWithTag("UICamera"):GetComponent("Camera")
	self._uiCamera = self._uiRootObj.Find("ui_camera"):GetComponent("Camera")
	self._3dUICamera = self._uiRootObj.Find("3d_ui_Camera"):GetComponent("Camera")
	
	self._uiMsgCanvasObj = self._uiRootObj.Find("msg_canvas")
	self._uiMainCanvasObj = self._uiRootObj.Find("main_canvas")
	self._uiMidCanvasObj = self._uiRootObj.Find("mid_canvas")
	self._uiTopCanvasObj = self._uiRootObj.Find("top_canvas")
	self._uiSystemCanvasObj = self._uiRootObj.Find("system_canvas") -- 系统 canvas ，用于 app 退出，屏幕变暗等操作 是最顶层的 canvas
	self._screenBrightnessImg = self._uiSystemCanvasObj.transform:Find("screen_brightness_img"):GetComponent("Image")
	self._uimapCanvasObj = self._uiRootObj.Find("map_canvas")
	self._uiSceneCanvasObj = self._uiRootObj.Find("scene_canvas")
	self._uiGuideCanvasObj = self._uiRootObj.Find("guide_canvas")
	self._worldSpaceCanvasObj = self._uiRootObj.Find("world_space_canvas")
	self._3dUICanvasObj = self._uiRootObj.Find("3d_canvas")
	self._3dUISceneCanvasObj = self._uiRootObj.Find("3d_scene_canvas")
	self._uiGuideLayerObj = self._uiGuideCanvasObj.transform:Find("ui_guide_layer").gameObject
	self._uiGuideLayerObj:SetActive(false)
	self._3duiGuideLayerObj = self._3dUICanvasObj.transform:Find("ui_guide_layer_3d").gameObject
	self._3duiGuideLayerObj:SetActive(false)
	self._goGuideLayerObj = self._uiGuideCanvasObj.transform:Find("go_guide_layer").gameObject
	local goHighLightMask = self._goGuideLayerObj:GetComponent("GoHighLightMask")
	goHighLightMask.mainCamera = Camera.main
	self._goGuideLayerObj:SetActive(false)

	self._uiMsgCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uiMainCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uiMidCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uiTopCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uiSystemCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uimapCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uiSceneCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._uiGuideCanvasObj:GetComponent("Canvas").worldCamera = self._uiCamera
	self._worldSpaceCanvasObj:GetComponent("Canvas").worldCamera = Camera.main
	self._camViewSize = self._uiCamera.orthographicSize

	self:InitPlaneDis()
	self:InitCanvasScaler()
end

CUIManager.InitCommonEvent = function(self)
	KeyDownEventListener.Get(self._uiRootObj).onClickF1 = LuaHelper.VoidDelegate(function()
		self:OpenWizardWnd()
	end)

	KeyDownEventListener.Get(self._uiRootObj).onSpecialTouch = LuaHelper.VoidDelegate(function()
		self:OpenWizardWnd()
	end)

	KeyDownEventListener.Get(self._uiRootObj).onClickF6 = LuaHelper.VoidDelegate(function()
		self:OpenPcSelectResWnd()
	end)

	KeyDownEventListener.Get(self._uiRootObj):AddKeyCodeEvent(KeyCode.F3, function()
		self:OpenCaijiEditor()
	end)

	UIEventListener.Get(self._uiMainCanvasObj).onTransformChildrenChanged = 
		LuaHelper.VoidDelegate( function() self:OnMainCanvasChildChanged() end )

	UIEventListener.Get(self._uimapCanvasObj).onTransformChildrenChanged = 
		LuaHelper.VoidDelegate( function() self:OnMapCanvasChildChanged() end )
end

CUIManager.InitPlaneDis = function(self)
	local func = function(canvasObj)
		local canvas = canvasObj.gameObject:GetComponent("Canvas")
		self._canvasToPlaneDis[canvasObj.name] = canvas.planeDistance
	end

	func(self._uiMainCanvasObj)
	func(self._uiMidCanvasObj)
	func(self._uiMsgCanvasObj)
end 

-- 设置CanvasScaler以兼容S8分辨率(2960*1440)
CUIManager.InitCanvasScaler = function(self)
	local func = function(canvasObj)
		local canvasScaler = canvasObj.gameObject:GetComponent("CanvasScaler")
		assert(canvasScaler)
		assert(canvasScaler.referenceResolution)

		local screenSize = Util.GetResolution()
		local screenW = screenSize.x
		local screenH = screenSize.y
		local uiW = canvasScaler.referenceResolution.x
		local uiH = canvasScaler.referenceResolution.y

		if screenW/screenH > uiW/uiH then
			canvasScaler.matchWidthOrHeight = 1
		else
			canvasScaler.matchWidthOrHeight = 0
		end
	end

	func(self._uiMainCanvasObj)
	func(self._uiMidCanvasObj)
	func(self._uiMsgCanvasObj)
	func(self._uiSceneCanvasObj)
	func(self._3dUICanvasObj)
	func(self._3dUISceneCanvasObj)
	func(self._uiTopCanvasObj)
end 

CUIManager.ResetCanvasToInitPlaneDis = function(self)
	local func = function(canvasObj)
		local canvas = canvasObj.gameObject:GetComponent("Canvas")
		if self._canvasToPlaneDis[canvasObj.name] then 
			canvas.planeDistance = self._canvasToPlaneDis[canvasObj.name]
		end 
	end

	func(self._uiMainCanvasObj)
	func(self._uiMidCanvasObj)
	func(self._uiMsgCanvasObj)
end 

CUIManager.HideCanvas = function(self)
	local HIDE_PLANE_DIS = -100
	local func = function(canvasObj)
		local canvas = canvasObj.gameObject:GetComponent("Canvas")
		canvas.planeDistance = HIDE_PLANE_DIS
	end

	func(self._uiMainCanvasObj)
	func(self._uiMidCanvasObj)
	func(self._uiMsgCanvasObj)
end 

CUIManager.SetCamViewSize = function(self)
	--需要入场动画播放完成调用
	local sizeScan = 8.55 --目前对比出来比较合适的参数
	local rate = Screen.width / Screen.height;
	local size = sizeScan / rate
	self._uiCamera.orthographicSize = size  
end

CUIManager.RecoverCamViewSize = function(self)
	self._uiCamera.orthographicSize = self._camViewSize
end

--传入全路径,initAsset放在这里就是为了可以统一在uiMgr中处理ui的Asset
CUIManager.InitAsset = function(self, prefabPath, useCache)
	local obj = Tool.Instantiate(prefabPath, nil, useCache)
	obj.transform.position = Vector3.zero
	return obj
end

-- CUIManager.InitAsset = function(self, prefabPath)

-- 	--UnityEngine.Profiling.Profiler.BeginSample("InitAsset " .. prefabPath)
	
--     if gGame:GetCacheMgr():IsHas(prefabPath) then
		
--     	local cacheGo = gGame:GetCacheMgr():Spawn(prefabPath)
--     	cacheGo.transform.position = Vector3.New(0, 0, 0) 
--     	return cacheGo

--     else
		
-- 		return self:InitAssetCommon(prefabPath)

--     end

	
--     --UnityEngine.Profiling.Profiler.EndSample()
-- end

CUIManager.GetAsset = function(self, prefabPath)
	--local prefabPath = "Assets/res/Prefabs/ui/" .. assetName .. ".prefab"
	-- local asset = ioo.resourceManager:LoadAsset(prefabPath, typeof(GameObject))
	-- return asset
end

-- 释放UImgr的资源
CUIManager.Release = function(self)
	if self._uiRootAsset then
		self._uiRootAsset = nil
	end
end

CUIManager.AddLogicIns = function(self, id, inc)
	self._LogicInsList[id] = inc
end

CUIManager.GetLogicIns = function(self, id)
	return self._LogicInsList[id]
end

CUIManager.GenerateId = function(self)
	self._counter = self._counter + 1
	return self._counter
end

--不在外部被调用的函数，id自动生成和指定的
CUIManager.CreateWindow = function(self, id, uiLogicClass, parentTran)
	assert(uiLogicClass ~= nil)
	parentTran = parentTran or self._uiMainCanvasObj.transform
	local LogicIns = uiLogicClass:New(id)
	--确保Init之后调用的
	LogicIns:OnCreate()
	LogicIns:SetParentTran(parentTran)
	-- 回调函数
	LogicIns:ShowSwitch(true)
	return LogicIns
end

-- 创造一个自动生成Id的界面,默认是在mainCanvas上
CUIManager.CreateWindowAuto = function(self, uiLogicClass, parentTran)
	local LogicInsId = self:GenerateId()
	local LogicIns = self:CreateWindow(LogicInsId, uiLogicClass, parentTran)
	self:AddLogicIns(LogicInsId, LogicIns)
	return LogicIns
end

-- 创造一个自定义Id的界面，(用于频繁打开关闭的界面使用)
-- customId使用"string",这些string最好在global_enum.lua的UICustomID中定义，避免重复
CUIManager.CreateWindowCustom = function(self, customId, uiLogicClass, parentTran)
	local LogicInsId = customId
	local LogicIns = self:GetLogicIns(LogicInsId)
	if LogicIns then
		LogicIns:ShowSwitch(true)
	else
		LogicIns = self:CreateWindow(LogicInsId, uiLogicClass, parentTran)
		self:AddLogicIns(LogicInsId, LogicIns)
	end

	return LogicIns
end

-- 销毁一个界面
CUIManager.DestroyWindow = function(self, uiLogicId, isDelay)	
	isDelay = isDelay or false
	local LogicIns = self:GetLogicIns(uiLogicId)
	if not LogicIns then return end
	--assert(LogicIns ~= nil, uiLogicId)

	-- PS:因为立即销毁界面会导致点击消息传递到场景中, 临时解决办法
	if isDelay then
		gGame:GetTimeManager():SetTimeOut(0.0, function()
			-- 在UIManager去除这个LogicIns
			LogicIns:Destroy()
			self._LogicInsList[uiLogicId] = nil
		end)
	else
		-- 在UIManager去除这个LogicIns
		LogicIns:Destroy()
		self._LogicInsList[uiLogicId] = nil
	end
end

CUIManager.CreateWindowCustomAsync = function(self, customId, uiLogicClass, parentTran)
	local assetPath = uiLogicClass.GetAsyncAssetPath()
	assert(assetPath ~= "", string.format("%s GetAsyncAssetPath() 获得无效的资源路径", customId))
	if assetPath ~= "" then
		local asyncLoadCallBack = function(path, assetObj)
			self:CreateWindowCustom(customId, uiLogicClass, parentTran)
			self._asyncLoadingLogicList[customId] = nil
		end
	
		local callBackId = gGame:GetGameObjectMgr():AddAsyncLoadCallBack(asyncLoadCallBack)
		ioo.resourceManager:LoadAssetAsyncForLua(assetPath, typeof(UnityEngine.GameObject), callBackId)
		self._asyncLoadingLogicList[customId] = true
	end

end

-- func(logicIns)
CUIManager.CallFuncForAsync = function(self, customId, func)
	assert(func, string.format("func参数为空"))
	
	local logincIns = self:GetLogicIns(customId)
	if logincIns then
		if func then
			func(logincIns)
		end
	else
		if self._asyncLoadingLogicList[customId] then
			-- 开协程等待
			local co = coroutine.start(function()
				local ins = nil
				while not ins do
					ins = self:GetLogicIns(customId)
					coroutine.step()
				end

				if func then
					func(ins)
				end

				--coroutine.stop(co)

			end)
		else
			warn(string.format("不存在实例 %s , 调用CallFuncForAsync失败", customId))
		end
	end
end

CUIManager.OnMainCanvasChildChanged = function(self)
	-- 协程等待是因为 lua ui实例初始化过程中已经触发OnMainCanvasChildChanged
	coroutine.start(function()
		coroutine.step()
		self:UpdateUIMainStatus()
	end)
end

CUIManager.OnMapCanvasChildChanged = function(self)
	-- 协程等待是因为 lua ui实例初始化过程中已经触发OnMapCanvasChildChanged
	coroutine.start(function()
		coroutine.step()
		self:UpdateUIMainStatus()
	end)
end

--更新主界面ui状态, 有其他界面打开的时候主界面UI要隐藏
CUIManager.UpdateUIMainStatus = function(self)
	local inFight = gGame:GetFightMgr():IsFighting()
	if inFight then return end 

	local isPlay = false

	local count = self._uiMainCanvasObj.transform.childCount
	for i = 0, count - 1 do
		local childTrans = self._uiMainCanvasObj.transform:GetChild(i)

		if self:IsChildWindowGo(childTrans.gameObject) then
			isPlay = true
		end
	end

	if not isPlay and self._uimapCanvasObj.transform.childCount > 0 then
		isPlay = true
	end

	local MainDlg = self:GetLogicIns(UICustomID.Main)
	local MainMenu = self:GetLogicIns(UICustomID.MainMenu)
	local isMainMenuShow = MainMenu and MainMenu:IsShowMenu()

	if MainDlg and MainDlg:IsShow() and (not isMainMenuShow) then
		MainDlg:SetMainObjMovePlaying(isPlay)
	end

	local chatInMainDlg = self:GetLogicIns(UICustomID.ChatInMain)
	if chatInMainDlg then
		chatInMainDlg:SetMove(isPlay)
	end
end

CUIManager.IsChildWindowGo = function(self, go)
	for id, ins in pairs(self._LogicInsList) do
		if id ~= UICustomID.Main and ins:IsRootGo(go) and ins:IsShow()

		and not GlobalEnum.UIExcludePageID[id] then
			return true
		end
	end

	return false
end

--单层控制;
CUIManager.SwitchUIEffectShow = function(self, show)
	if self._uiRootObj then
		self._uiRootObj:SetActive(true)
	end
	
	if self._uiMainCanvasObj then
		self._uiMainCanvasObj:SetActive(true)
	end

	for k, v in pairs(self._LogicInsList) do
		if k == "UiEffect" and v then 
			v:ShowSwitch(show)
		end
	end
end

--UI显示的总体控制;
CUIManager.SwitchShow = function(self, show)
	for k, v in pairs(self._LogicInsList) do
		if v then 
			v:ShowSwitch(show)
		end
	end

	if self._floatMenu then 
		self._floatMenu:ShowSwitch(show)
	end
	if self._floatDialog then
		self._floatDialog:ShowSwitch(show)
	end
end

-- 有保留的Change Scene Clear UI
CUIManager.ChangeSceneClearUI = function(self)
	--获取keys进行删除，避免嵌套删除同时又遍历self._LogicInsList时遍历异常
	local logicKeys = table.keys(self._LogicInsList) or {}
	for k, v in pairs(logicKeys) do
		local logicIns = self._LogicInsList[v]
		if logicIns and (not logicIns:IsDontDestroyOnLoad()) then

			logicIns:Destroy()
			self._LogicInsList[v] = nil
		end
	end
	
	self:OnClear()
end

-- 无保留的Clear UI
CUIManager.Clear = function(self)
	--获取keys进行删除，避免嵌套删除同时又遍历self._LogicInsList时遍历异常
	local logicKeys = table.keys(self._LogicInsList) or {}
	for k, v in pairs(logicKeys) do

		local logicIns = self._LogicInsList[v]
		if logicIns then
			logicIns:Destroy()
			self._LogicInsList[v] = nil
		end
	end

	self:OnClear()
end

CUIManager.OnClear = function(self)
	self._counter = 0

	if self._floatMenu then 
		self._floatMenu:Destroy()
		self._floatMenu = nil
	end
	if self._floatDialog then
		self._floatDialog:Destroy()
		self._floatDialog = nil
	end

	self._waitingUI = nil
	self._waitingUIRetain = 0
	self:StopWaitingTimer()

	gGame:GetGuideMgr():Clear()
end

CUIManager.DestroyOtherViewExcept = function(self, exceptLogicIds)
	if not exceptLogicIds then
		local logicKeys = table.keys(self._LogicInsList) or {}
		for k, v in pairs(logicKeys) do
			if self._LogicInsList[v] then
				self._LogicInsList[v]:Destroy()
				self._LogicInsList[v] = nil
			end
		end
		self._LogicInsList = {}

		return
	end

	local exceptLogicDic = {}
	for k,v in ipairs(exceptLogicIds) do
		exceptLogicDic[v] = self._LogicInsList[v]
	end
	if self._LogicInsList[UICustomID.Waiting] then
		exceptLogicDic[UICustomID.Waiting] = self._LogicInsList[UICustomID.Waiting]
	end

	local logicKeys = table.keys(self._LogicInsList) or {}
	for k, v in pairs(logicKeys) do
		if self._LogicInsList[v] and not exceptLogicDic[v] then
			self._LogicInsList[v]:Destroy()
			self._LogicInsList[v] = nil
		end
	end
	self._LogicInsList = {}

	for k,v in pairs(exceptLogicDic) do
		self._LogicInsList[k] = v
	end
end

CUIManager.ShowSwitchWindows = function(self, logicIds, isShow)
	table.foreachi(logicIds, function(_, logicId)
		local logicIns = self:GetLogicIns(logicId)
		if logicIns then
			logicIns:ShowSwitch(isShow)
		end
	end)
end

-- uimanger自己的销毁
CUIManager.Destroy = function(self)
	GameObject.Destroy(self._uiRootObj)
	self:Clear()
end

CUIManager.GetRootObj = function(self)
	return self._uiRootObj
end

CUIManager.GetSceneCanvasObj = function(self)
	return self._uiSceneCanvasObj
end

CUIManager.GetMsgCanvasObj = function(self)
	return self._uiMsgCanvasObj
end

CUIManager.GetMainCanvasObj = function(self)
	return self._uiMainCanvasObj
end

CUIManager.GetMainCanvasTr = function(self)
	return self._uiMainCanvasObj.transform
end

CUIManager.GetMidCanvasObj = function(self)
	return self._uiMidCanvasObj
end

CUIManager.GetMidCanvasTr = function(self)
	return self._uiMidCanvasObj.transform
end

CUIManager.GetTopCanvasObj = function(self)
	return self._uiTopCanvasObj
end

CUIManager.GetTopCanvasTr = function(self)
	return self._uiTopCanvasObj.transform
end

CUIManager.GetMapCanvasObj = function(self)
	return self._uimapCanvasObj
end

CUIManager.GetSystemCanvasObj = function(self)
	return self._uiSystemCanvasObj
end

CUIManager.GetScreenBrightnessImg = function(self)
	return self._screenBrightnessImg
end

CUIManager.GetUIGuideLayerObj = function(self)
	return self._uiGuideLayerObj
end

CUIManager.Get3dUIGuideLayerObj = function(self)
	return self._3duiGuideLayerObj
end

CUIManager.GetUIGuideCanvasObj = function(self)
   return self._uiGuideCanvasObj
end

CUIManager.GetWorldSpaceCanvasObj = function(self)
	return self._worldSpaceCanvasObj
end 

CUIManager.Get3dUICanvasObj = function(self)
	return self._3dUICanvasObj
end 

CUIManager.Get3dUISceneCanvasObj = function(self)
	return self._3dUISceneCanvasObj
end 

CUIManager.GetGoGuideLayerObj = function(self)
	return self._goGuideLayerObj
end

CUIManager.GetUICamera = function(self)
	if not self._uiCamera then print("#_#Has no UI Camera!!!") end
	return self._uiCamera
end

CUIManager.Get3dUICamera = function(self)
	return self._3dUICamera
end 

CUIManager.ActiveMainCanvas = function(self, active)
	self._uiMainCanvasObj.gameObject:SetActive(active)
end

CUIManager.ShowWaiting = function(self, timeOut)
	self._curWaitingUITimeout = timeOut or self._defWaitingUITimeout
	if not self._waitingUI then
		self._waitingUI = self:CreateWindowCustom(UICustomID.Waiting, CUIPnlConnectingLogic, self._uiTopCanvasObj.transform)
	end
	self._waitingUI:SetAsLastSibling()
	self._waitingUIRetain = self._waitingUIRetain + 1
	self:StartWaitingTimer()
end

CUIManager.HideWaiting = function(self)
	self._waitingUIRetain = self._waitingUIRetain - 1
	if self._waitingUIRetain <= 0 then
		self._waitingUIRetain = 0
		self:StopWaitingTimer()
		self:DestroyWindow(UICustomID.Waiting)
		self._waitingUI = nil
	end
end

CUIManager.StopWaitingTimer = function(self)
	if self._waitingTimer then
		gGame:GetTimeManager():RemoveTimer(self._waitingTimer)
		self._waitingTimer = nil
	end
end 

CUIManager.StartWaitingTimer = function(self)
	self:StopWaitingTimer()
	self._waitingTimer = gGame:GetTimeManager():SetTimeOut(self._curWaitingUITimeout, function()
		self._waitingUIRetain = 0
		self:HideWaiting()
	end)
end

CUIManager.OpenProcessDialog = function(self, data)
	local parentTran = gGame:GetUIMgr():GetTopCanvasTr()
	local dialogIns = self:CreateWindowCustom(UICustomID.ProcessDialog, CUIProcessDialogLogic, parentTran)
	dialogIns:SetData(data)
end

CUIManager.OpenRewardFloatDialog = function(self, data)
	local parentTran = gGame:GetUIMgr():GetMsgCanvasObj().transform
	local dialogLocin = self:CreateWindowCustom(UICustomID.MsgDialog, CUIRewardFloatDialogLogic, parentTran)
	dialogLocin:SetAsLastSibling()
	dialogLocin:OpenDialog(data)
end

-- Tips提示，支持文本内容及配表消息ID（不支持参数拼接），配表消息ID要与服务端统一(eg:sys0001 -> #S(sys0001))
-- 配表消息：EXPORT\client_doc
CUIManager.OpenFloatDialog = function(self, text)
	self:ShowClienMsg(2, text)
end

-- Tips提示，只支持配表消息ID（不支持文本内容） msgId:sys0001 ...：拼接参数,对应消息体中的%1s,%2s
-- 配表消息：EXPORT\client_doc
CUIManager.OpenFloatDialogByMsgId = function(self, msgId, ...)
	local msgData = gGame:GetDataMgr():GetMsgData()
	local fmtStr = msgData:ParseDefineStr(msgId, {...})
	self:OpenFloatDialog(fmtStr)
end

--显示滚动公告
CUIManager.OpenScrollNotice = function(self, text)
	local CUIPnlAnnounceLogic = Import("logic/ui/pnl_announce/ui_pnl_announce_logic").CUIPnlAnnounceLogic
	local parentTran = gGame:GetUIMgr():GetMsgCanvasObj().transform
	local noticeLocin = self:CreateWindowCustom(UICustomID.ScrollNotice, CUIPnlAnnounceLogic, parentTran)
	noticeLocin:AddAnnouncement(text)
end

CUIManager.OpenFloatMenu = function(self, go, targetPos)
	self._floatMenu = UIFloatMenu:New(go, targetPos)
	return self._floatMenu
end

CUIManager.ClearFloatMenu = function(self)
	if self._floatMenu then 
		self._floatMenu:Destroy() 
	end
end

CUIManager.OpenAlertDialog = function(self, titleStr, contextStr, btnContextStr, btnCallback, isMode, isHideClose, closeBtnCallback)
	local alertDialog = self:CreateWindowCustom(UICustomID.PnlAlertDialog, CUIPnlAlertDialogLogic, self._uiTopCanvasObj.transform)
	alertDialog:UpdateView(titleStr, contextStr, btnContextStr, btnCallback, isMode, isHideClose, closeBtnCallback)
	return alertDialog
end

-- 对‘二次确认对话框’的各种非常用设置，需要使用表来传递参数
-- argsTable = {}
-- argsTable.dontRemindCallback
-- argsTable.countDownCalback
-- argsTable.closeTimeout
-- argsTable.isOnTop               (true or false) 是否将对话框层级放到最上层
-- argsTable.isHideClose           (true or false) 是否隐藏退出按键
-- 通用两个按钮的二次弹框
CUIManager.OpenReconfirmDialog = function(self, titleStr, contextStr, leftBtnContextStr, leftBtnCallback, rightBtnContextStr, rightBtnCallback, isMode, argsTable)
	local reconfirmDialog = self:CreateWindowCustom(UICustomID.PnlConfirmDialog, CUIPnlConfirmDialogLogic, self._uiTopCanvasObj.transform)
	reconfirmDialog:UpdateView(titleStr, contextStr, leftBtnContextStr, leftBtnCallback, rightBtnContextStr, rightBtnCallback, isMode, argsTable)
	return reconfirmDialog
end

CUIManager.OpenSimpleReconfirmDialog = function(self, contextStr, leftBtnContextStr, leftBtnCallback, rightBtnContextStr, rightBtnCallback, closeBtnCallback, isMode, argsTable)
	local reconfirmDialog = gGame:GetUIMgr():CreateWindowCustom(UICustomID.PnlSimpleReconfirm, CUIPnlSimpleReconfirmLogic)
	reconfirmDialog:InitData(contextStr, leftBtnContextStr, leftBtnCallback, rightBtnContextStr, rightBtnCallback, closeBtnCallback, isMode, argsTable)
	return reconfirmDialog
end

-- 打开通用改名界面
-- titleStr：标题  contextStr：默认显示的内容
CUIManager.OpenReNamePnl = function(self, titleStr, contextStr, btnContextStr, btnCallback)
	local reNamePnl = self:CreateWindowCustom(UICustomID.PnlReName, CUIPnlReNameLogic)
	titleStr = titleStr or TEXT("改名")
	contextStr = contextStr or TEXT("点击输入新的名字")
	btnContextStr = btnContextStr or TEXT("确认")

	reNamePnl:SetTitle(titleStr)
	reNamePnl:SetDefaultContent(contextStr)
	reNamePnl:SetBtnName(btnContextStr)

	local confirmBtnCb = function(strName)
		btnCallback(strName)
		self:DestroyWindow(reNamePnl:GetId())
	end

	reNamePnl:SetClickFunc(confirmBtnCb)
end

-- 传入需要显示的所有货币的类型（形式为表），如 XXX:ShowMoneyLogic({CommonEnum.CURRENCY.CASH, CommonEnum.CURRENCY.GOLD})
-- 表示显示银两和金锭（没有参数则默认显示银两，金锭，灵玉三种）
CUIManager.ShowMoneyLogic = function(self, currencyTypesTable)
	local parent = self:GetTopCanvasObj()
	local moneydlg = gGame:GetUIMgr():CreateWindowCustom("MoneyLogic", CUIPnlMoneyLogic, parent.transform)
	moneydlg:SetShowCurrencyType(currencyTypesTable)
	moneydlg:ShowSwitch(true)
end

CUIManager.HideMoneyLogic = function(self)
	local moneydlg = gGame:GetUIMgr():GetLogicIns("MoneyLogic")
	if not moneydlg then return end
	moneydlg:ShowSwitch(false)
end

CUIManager.CreateIcon = function(self, path, iType, parent)
	iType = iType or 1

	path = path or CommonEnum.IconTypeToResPath[iType]

	if not path then return end

	local goAsset = ioo.resourceManager:LoadAsset("Assets/res/Prefabs/ui/icon/icon" ..iType.. ".prefab", typeof(GameObject))
	local go = GameObject.Instantiate(goAsset)
	local goRectTransform = go:GetComponent("RectTransform")
	local goImage = go.transform:Find("Image"):GetComponent("Image")

	local iconAsset = ioo.resourceManager:LoadAsset(path, typeof(UnityEngine.Sprite))
	if iconAsset ~= nil then
		goImage.sprite = iconAsset
	end

	if parent then
		goRectTransform.parent = parent
	end

	goRectTransform.localPosition = Vector3(0, 0, 0)
	goRectTransform.localRotation = Quaternion.Euler(0, 0, 0)
	goRectTransform.localScale = Vector3(1, 1, 1)

	return go
end

-- 创建角色半身像图标，配置表：造型总表.xls(image_path，半身像)
CUIManager.CreateRoleHeadIconSprite = function(self, icon)
	if not icon then return end
	local path = ALL_RES_ID[icon].image_path
	if path == "" then error("缺少造型总表图片资源路径配置，造型Id:"..icon) return end
	local asset = self:LoadIconAsset(path)
	if not asset then return end
	return asset
end

-- 创建角色图标，配置表：造型总表.xls(icon_path，头像)
CUIManager.CreateHeadIconSprite = function(self, icon)
	if not icon then return end
	local path = ALL_RES_ID[icon].icon_path
	if path == "" then error("缺少造型总表图片资源路径配置，造型Id:"..icon) return end
	local asset = self:LoadIconAsset(path)
	if not asset then return end
	return asset
end

CUIManager.LoadIconAsset = function(self, path)
	if not path then return end

	local asset = ioo.resourceManager:LoadAsset(path, typeof(UnityEngine.Sprite))
	if tolua.isnull(asset) then error("加载图片资源失败，path："..path) return end

	return asset
end

CUIManager.CreateUIEffect = function(self, path, isTop)
	local obj = nil
	if not self:GetLogicIns(UICustomID.UiEffect) then
		local CUIUiEffectLogic = Import("logic/ui/ui_effect/ui_ui_effect_logic").CUIUiEffectLogic
		self:CreateWindowCustom(UICustomID.UiEffect, CUIUiEffectLogic, self._uiSceneCanvasObj.transform)
	end
	
	if self:GetLogicIns(UICustomID.UiEffect) then
		obj = self:GetLogicIns(UICustomID.UiEffect):AddMianEffectPrefabs(path, isTop)
	end
	return obj
end


CUIManager.SetResMatch = function(self, screenW, screenH)
	
	local setCanvasScaleFunc = function(canvasObj, screenWidth, screenHeight)
		local canvasScaler = canvasObj.gameObject:GetComponent("CanvasScaler")
		assert(canvasScaler)
		assert(canvasScaler.referenceResolution)
		local uiW = canvasScaler.referenceResolution.x
		local uiH = canvasScaler.referenceResolution.y
		if screenWidth/screenHeight > uiW/uiH then
			canvasScaler.matchWidthOrHeight = 1
		else
			canvasScaler.matchWidthOrHeight = 0
		end
	end
	
	setCanvasScaleFunc(self._uiMainCanvasObj, screenW, screenH)
	setCanvasScaleFunc(self._uiMidCanvasObj, screenW, screenH)
	setCanvasScaleFunc(self._uiMsgCanvasObj, screenW, screenH)
	setCanvasScaleFunc(self._uiSceneCanvasObj, screenW, screenH)

end

CUIManager.CreateAntoUIEffect = function(self, path)
	if not self:GetLogicIns(UICustomID.UiEffect) then
		local CUIUiEffectLogic = Import("logic/ui/ui_effect/ui_ui_effect_logic").CUIUiEffectLogic
		self:CreateWindowCustom(UICustomID.UiEffect, CUIUiEffectLogic, self._uiSceneCanvasObj.transform)
	end
	if self:GetLogicIns(UICustomID.UiEffect) then
		self:GetLogicIns(UICustomID.UiEffect):AddAntoEffectPrefabs(path)
	end
end

CUIManager.DeleteUIEffect = function(self, path)
	if self:GetLogicIns(UICustomID.UiEffect) then
		self:GetLogicIns(UICustomID.UiEffect):DeleteMianEffectPrefabs(path)
	end
end

--创建【寻路】或者【巡逻】的特效
CUIManager.CreateUIAutoRunEffect = function(self)
	local guajiData = gGame:GetDataMgr():GetPatrolHangUpData()
	local isHangUping = guajiData:GetIsHangUping()

	local orgSlgData = gGame:GetDataMgr():GetOrgSlgData()
	local isSlgXunluo = orgSlgData:GetIsXunluoIng()

	--在挂机、联盟巡逻的话显示巡逻，否则显示寻路
	if isHangUping or isSlgXunluo then
		self:CreateUIXunLuoEffect()
	else
		self:CreateUIXunluEffect()
	end
end

--销毁【寻路】,检查销毁【巡逻】的特效
CUIManager.CheckDeleteUIAutoRunEffect = function(self)
	self:DeleteUIEffect(UI_EFFECT.ANTO_XUNLU_EFFECT)

	--挂机中不删除巡逻特效
	local guajiData = gGame:GetDataMgr():GetPatrolHangUpData()
	local isHangUping = guajiData:GetIsHangUping()

	--联盟Slg巡逻中不删除巡逻特效
	local orgSlgData = gGame:GetDataMgr():GetOrgSlgData()
	local isSlgXunluo = orgSlgData:GetIsXunluoIng()

	if not isHangUping and not isSlgXunluo then
		self:DeleteUIEffect(UI_EFFECT.XUNLUO_EFFECT)
	end
end

--销毁【寻路】【巡逻】的特效
CUIManager.DeleteAllAutoRunEfect = function(self)
	self:DeleteUIEffect(UI_EFFECT.ANTO_XUNLU_EFFECT)
	self:DeleteUIEffect(UI_EFFECT.XUNLUO_EFFECT)
end

--创建自动寻路的特效
CUIManager.CreateUIXunluEffect = function(self)
	self:CreateUIEffect(UI_EFFECT.ANTO_XUNLU_EFFECT, true)
end

--销毁自动寻路的特效
CUIManager.DeleteUIXunluEffect = function(self)
	self:DeleteUIEffect(UI_EFFECT.ANTO_XUNLU_EFFECT)
end

--创建巡逻中的特效
CUIManager.CreateUIXunLuoEffect = function(self)
	local effectObj = self:CreateUIEffect(UI_EFFECT.XUNLUO_EFFECT, true)
end

--销毁巡逻中的特效
CUIManager.DeleteUIXunLuoEffect = function(self)
	self:DeleteUIEffect(UI_EFFECT.XUNLUO_EFFECT)
end

--提示客户端的漂浮提示
CUIManager.ShowClienMsg = function(self, iMode, msgStr)
	local msgData = gGame:GetDataMgr():GetMsgData()
	msgData:ReceiveSysData({iMode = iMode, msgStr = msgStr})
end

--提示客户端的提示(包括漂浮提示和筋斗云提示)
CUIManager.ShowClientMiscMsg = function(self, msgId)
	local msgData = gGame:GetDataMgr():GetMsgData()
	msgData:ReceiveDefinedMessage({msgId = msgId, argsTable = {}})
end

-- 打开一个面板，id：Design\EXPORT\J界面配置\界面配置.xls 添加
CUIManager.OpenPanel = function(self, id)
	if not id then return end
	local pnlInfo = UIPnl[id]
	if not pnlInfo then error("获取界面配置失败,ID:"..id) return end

	-- 检查是否满足打开界面的等级限制
	local heroData = gGame:GetDataMgr():GetHeroData()
	local heroGrade = heroData:GetGrade()
	if heroGrade < pnlInfo.LimitLevel then 
		self:OpenFloatDialog(string.format("%s需达到%s级开启", pnlInfo.Desc, pnlInfo.LimitLevel))
		return false
	end 

	local uiId = pnlInfo.UICustomID
	local uiLogic = Import(pnlInfo.LogicPath)[pnlInfo.LogicName]
	local uiIns = self:CreateWindowCustom(uiId, uiLogic)
	local switchFunc = pnlInfo['SwitchFunc']
	if switchFunc and switchFunc ~= '' then
		uiIns[switchFunc](uiIns)
	end
	return uiIns
end

-- 返回的uiLogic自己管理，ui_manager只负责创建
-- 创建物品奖励通用小格子, cType:ZH00006, count:数量，不填或填1不显示, itemType:EQUIP,ITEM,没有传入nil
CUIManager.CreateRewardGrid = function(self, cType, count, parentTran, scrollingTr, itemType)
	count = count or 1
	parentTran = parentTran or self._uiMainCanvasObj.transform
	local uiLogic = CUIBtnGaidLogic:New(cType)
	uiLogic:OnCreate()
	uiLogic:SetParentTran(parentTran)
	uiLogic:ShowSwitch(true)
	
	uiLogic:InitTypeData(cType, count, itemType)
	uiLogic:InitEvent(function()
		gGame:GetTipMgr():OpenTipDlgWithNoBtnByType(cType, uiLogic._view._ImgC_GaidBg.gameObject, itemType)
	end)
	if scrollingTr then
		uiLogic:SetScrolling(scrollingTr)
	end
	return uiLogic
end

CUIManager.CreateRewardGridByImg = function(self, cType, count, parentTran, itemType)
	count = count or 1
	parentTran = parentTran or self._uiMainCanvasObj.transform
	local uiLogic = CUIBtnGaidBlackImgLogic:New(cType)
	uiLogic:OnCreate()
	uiLogic:SetParentTran(parentTran)
	uiLogic:ShowSwitch(true)
	
	uiLogic:InitTypeData(cType, count, itemType)
	uiLogic:InitEvent(function()
		
		gGame:GetTipMgr():OpenTipDlgWithNoBtnByType(cType, uiLogic._view._root, itemType)
	end)
	
	return uiLogic
end

-- 返回的uiLogic自己管理，ui_manager只负责创建
--创建有滑动界面的滚动条，返回创建的界面列表，回调方法创建和初始化页面的信息
--cloneObj克隆界面的对象, cloneParent克隆界面的父节点, dataList克隆的列表, count每页的数量, func回调初始化克隆对象
CUIManager.CreateScrollPage = function(self, cloneObj, cloneParent, dataList, count, func)
	local pageList = {}
	local pageObj= nil
	local index = 0
	for _, value in ipairs(dataList) do
		if index % count == 0 then
			pageObj = GameObject.Instantiate(cloneObj)
			pageObj.gameObject:SetActive(true)
			pageObj.transform:SetParent(cloneParent, false)
			table.insert(pageList, pageObj)
		end
		index = index + 1
		func(pageObj.transform, value)
	end
	return pageList
end

-- 返回的uiLogic自己管理，ui_manager只负责创建
CUIManager.CreateUILogic = function(self, uiLogicClass, parentTran, id)
	id = id or -1
	return self:CreateWindow(id, uiLogicClass, parentTran)
end

CUIManager.OnChangeScene = function(self)
	-- 通过任务寻路切场景不销毁UI
	local isTrackPause = gGame:GetTrackMgr():IsTrackPause()
	local sceneMgr = gGame:GetSceneMgr()

	if not isTrackPause then
		self:ChangeSceneClearUI()
	else

		if not sceneMgr:IsMainScene() or not sceneMgr:IsPrevMainScene() then
			self:ChangeSceneClearUI()
		else
			for _, logicId in ipairs(GlobalEnum.COMMON_CHANGE_SCENE_LOGIC) do
				self:DestroyWindow(logicId)
			end
		end
	end
end

-- 创建一个全屏UI，遮挡界面点击事件
CUIManager.ShowSwitchEmptyUi = function(self, isShow)
	if isShow then

		if IsNull(self._emptyUi) then
			self._emptyUi = Tool.Instantiate("Assets/res/Prefabs/ui/q6main/PnlEmpty.prefab", self:GetTopCanvasObj().transform)
		end
		
	else
		if not IsNull(self._emptyUi) then
			GameObject.Destroy(self._emptyUi)
		end

		self._emptyUi = nil
	end
end

-- 打开巫师指令窗口
CUIManager.OpenWizardWnd = function(self)
	local otherData = gGame:GetDataMgr():GetOtherData()

	if otherData:IsWizardPermission() then
		self:CreateWindowCustom(UICustomID.Chat, CUIChatNewLogic, self:GetTopCanvasTr())
	end
end

-- 打开采集物编辑器
CUIManager.OpenCaijiEditor = function(self)
	local otherData = gGame:GetDataMgr():GetOtherData()

	if otherData:IsWizardPermission() then
		self:CreateWindowCustom(UICustomID.CaijiEditor, CUIPnlCaijiItemsEditorLogic)
	end
end

-- 打开PC平台下的分辨率选择器
CUIManager.OpenPcSelectResWnd = function(self)
	local selectPnlLogin = self:GetLogicIns(UICustomID.PnlSelectResolution)

	if selectPnlLogin then
		self:DestroyWindow(UICustomID.PnlSelectResolution)
	else
		self:CreateWindowCustom(UICustomID.PnlSelectResolution, CUIPnlSelectResolutionLogic)
	end
end

-- 通用纯文本tips框, txtTips:显示内容, width:Tips宽度, clickGo:Tips弹出定位Go
CUIManager.ShowCommonTxtTips = function(self, txtTips, width, clickGo)
	local uiIns = self:CreateWindowCustom(UICustomID.PnlCommonTips, CUIPnlCommonTxtTipsLogic, self:GetTopCanvasTr())
	uiIns:SetTips(txtTips, width, clickGo)
end

local CANNT_BUY_MSG = TEXT("此物品无法在商城购买")
local CUIPnlTradeLogic = Import("logic/ui/trade/pnl_trade/ui_pnl_trade_logic").CUIPnlTradeLogic
-- 显示[商城]-->[商会]-->[购买]指定物品的购买界面
CUIManager.ShowCanBuyItemsInShop = function(self, itemType)
	local tradeData = gGame:GetDataMgr():GetTradeData()
	local huojiaType = tradeData:GetItemHuojiaType(itemType)

	if huojiaType then
		local stallLogicInc = gGame:GetUIMgr():CreateWindowCustom(UICustomID.PnlShop, CUIPnlTradeLogic)
		stallLogicInc:ShowCanBuyItems(itemType)
	else
		gGame:GetUIMgr():OpenFloatDialog(CANNT_BUY_MSG)
	end
end